model <- keras_model_sequential() %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dense(units = 512, activation = "relu") %>%
layer_dense(units = 11, activation = "softmax")Projekt Automatyczna Analiza Obrazu
Tematyka zadania
Celem tego projektu jest zbudowanie modelu konwolucyjnej sieci neuronowej służącej do klasyfikacji dzieł sztuki ze względu na gatunek (11 etykiet) oraz stylów malarskich (27 etykiet).
Zbiór danych którego użylismy do trenowania modeli jest WikiArt, zawiera on ponad 84 tysiące różnych obrazów. Zbiór ten funkcjonuje w otwartym dostępie i jest darmowy do niekomercyjnego użytku.
Największą trudność zadania stanowi fakt, że klasyfikacja obrazów jest zadaniem o charakterze abstrakcyjnym w zestawieniu z klasyfikacją przedmitów, ludzi lub zwirząt.
Dodatkowo specyfika zadania uniemożliwa wykorzystanie augmentacji, wynika to z tego, że dla danego obrazu możliwy jest tylko oryginalny sposób reprezentacji, zgodny z projektem artysty.
Klasyfikacja gatunku obrazu
Każdy z obrazów posiada etykietę wskazującą na gatunek obrazu:
0 - Malarstwo abstrakcyjne;
1 - Pejzaż miejski;
2 - Malarstwo rodzajowe;
3 - Ilustracja;
4 - Pejzaż;
5 - Malarstwo nagie;
6 - Portret;
7 - Malarstwo religijne;
8 - Szkic;
9 - Martwa natura;
10 - Gatunek nieznany.
Pierwszy projekt sieci
Pierwsza testowana przez nas architekutra sieci jest stosunkowo prosta, ponieważ składa się jedynie z 4 warstw konwolucyjnych i łączących (w tym wypadku - “max poolingowych”) ze stosunkowo niewielką ilością filtrów.
Kod
Model: "sequential"
________________________________________________________________________________
Layer (type) Output Shape Param #
================================================================================
conv2d_3 (Conv2D) (None, 148, 148, 32) 896
________________________________________________________________________________
max_pooling2d_3 (MaxPooling2D) (None, 74, 74, 32) 0
________________________________________________________________________________
conv2d_2 (Conv2D) (None, 72, 72, 64) 18496
________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D) (None, 36, 36, 64) 0
________________________________________________________________________________
conv2d_1 (Conv2D) (None, 34, 34, 128) 73856
________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D) (None, 17, 17, 128) 0
________________________________________________________________________________
conv2d (Conv2D) (None, 15, 15, 128) 147584
________________________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 7, 7, 128) 0
________________________________________________________________________________
flatten (Flatten) (None, 6272) 0
________________________________________________________________________________
dense_1 (Dense) (None, 512) 3211776
________________________________________________________________________________
dense (Dense) (None, 11) 5643
================================================================================
Total params: 3,458,251
Trainable params: 3,458,251
Non-trainable params: 0
________________________________________________________________________________
Szkolenie w każdej epoce odbywało się na 3200 obrazkach, a walidacja była przeprowadzana na 1600 obrazkach.
Funkcją optymalizującą był “Adam” oraz zastosowane zostały następujące callbacki:
Zapisywanie modelu po każdej epoce;
Przerwanie procesu uczenia, jeżeli celność nie poprawi się na zbiorze walidacyjnym po 5 epokach.
Przy tej strukturze sieć szkoliła się przez 28 epok, kończąc proces uczenia przez zastosowanie callbacków ze względu na brak poprawy celności na zbiorze walidacyjnym.
Widać że nastąpiło zjawisko przeuczenia. Najwyższą celnością na zbiorze walidacyjnym było ~45%.
Drugi projekt sieci
Druga architektura składa się z większej liczby warstw konwolucyjnych oraz większej ilości filtrów. Dodatkowo tym razem dodaliśmy warstwy dropout’ów w celu redukcji przeuczenia sieci.
Kod
model <- keras_model_sequential() %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu",
input_shape = c(150, 150, 3)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.2) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.3) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.3) %>%
layer_flatten() %>%
layer_dense(units = 256, activation = "relu") %>%
layer_dense(units = 54, activation = "relu") %>%
layer_dropout(rate = 0.5) %>%
layer_dense(units = 11, activation = "softmax")Model: "sequential_1"
________________________________________________________________________________
Layer (type) Output Shape Param #
================================================================================
conv2d_9 (Conv2D) (None, 148, 148, 128) 3584
________________________________________________________________________________
conv2d_8 (Conv2D) (None, 146, 146, 128) 147584
________________________________________________________________________________
max_pooling2d_6 (MaxPooling2D) (None, 73, 73, 128) 0
________________________________________________________________________________
dropout_3 (Dropout) (None, 73, 73, 128) 0
________________________________________________________________________________
conv2d_7 (Conv2D) (None, 71, 71, 64) 73792
________________________________________________________________________________
conv2d_6 (Conv2D) (None, 69, 69, 64) 36928
________________________________________________________________________________
max_pooling2d_5 (MaxPooling2D) (None, 34, 34, 64) 0
________________________________________________________________________________
dropout_2 (Dropout) (None, 34, 34, 64) 0
________________________________________________________________________________
conv2d_5 (Conv2D) (None, 32, 32, 128) 73856
________________________________________________________________________________
conv2d_4 (Conv2D) (None, 30, 30, 32) 36896
________________________________________________________________________________
max_pooling2d_4 (MaxPooling2D) (None, 15, 15, 32) 0
________________________________________________________________________________
dropout_1 (Dropout) (None, 15, 15, 32) 0
________________________________________________________________________________
flatten_1 (Flatten) (None, 7200) 0
________________________________________________________________________________
dense_4 (Dense) (None, 256) 1843456
________________________________________________________________________________
dense_3 (Dense) (None, 54) 13878
________________________________________________________________________________
dropout (Dropout) (None, 54) 0
________________________________________________________________________________
dense_2 (Dense) (None, 11) 605
================================================================================
Total params: 2,230,579
Trainable params: 2,230,579
Non-trainable params: 0
________________________________________________________________________________
Uczenie tym razem odbywało się na 51200 obrazach w epoce, a następnie model walidowany był na 12800 obrazach.
Funkcją optymalizującą również był “Adam” oraz zastosowane były te same callbacki co przy wcześniejszej architekturze.
Niestety, także i przy tej architekturze nastąpiło zjawisko przeuczenia (nawet szybciej niż w przypadku sieci poprzedniej) osiągając accuracy maksymalnie na poziomie 0.45.
Trzeci projekt sieci
Tym razem zdecydowaliśmy się użyć wcześniej przeszkolonej sieci ResNet jako części konwolucyjnej. Ze względu na ograniczone zasoby obliczeniowe użyliśmy wersji ResNet50.
ResNet50 to wariant modelu ResNet, który składa się z 48 warstw konwolucyjnych, jednej warstwy łączącej (“Max Pool”) i jednej warstwy łączącej (“Average Pool”). ResNet został zaprojektowany w celu dodawania większej liczby warstw konwolucyjnych do sieci CNN, bez napotkania problemu zanikającego gradientu, za pomocą koncepcji połączeń rezydualnych.
conv_base <- application_resnet50(
weights = "imagenet",
include_top = F,
input_shape = c(224,224,3)
)freeze_weights(conv_base)
unfreeze_weights(conv_base, from = "conv5_block3_2_conv")Odmrażamy dwa ostatnie bloki konwolucyjne i normalizujące partię w celu dostrojenia sieci do naszego zadania.
Kod
model <- keras_model_sequential() %>%
conv_base %>%
layer_flatten() %>%
layer_dense(units = 512, activation = "relu") %>%
layer_dense(units = 11, activation = "softmax")Model: "sequential_2"
_____________________________________________________________________
Layer (type) Output Shape Param #
=====================================================================
resnet50 (Functional) (None, 7, 7, 2048) 23587712
_____________________________________________________________________
flatten_2 (Flatten) (None, 100352) 0
_____________________________________________________________________
dense_6 (Dense) (None, 512) 51380736
_____________________________________________________________________
dense_5 (Dense) (None, 11) 5643
=====================================================================
Total params: 74,974,091
Trainable params: 54,801,931
Non-trainable params: 20,172,160
_____________________________________________________________________
Sieć uczona była na pełnym zbiorze treningowym przy użyciu optimizera “Adam” i tych samch callbacków co przy poprzednich architekturach.
W tym przypadku zjawisko przeuczenia nastąpiło nawet szybiciej niż przy poprzednich architekturach.
Czwarty projekt sieci
Kod
model <- keras_model_sequential() %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3),
input_shape = c(224, 224, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.2) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.3) %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dropout(rate = 0.5) %>%
layer_dense(units = 512, activation = "relu") %>%
layer_activity_regularization(l2 = 0.001) %>%
layer_dense(units = 11, activation = "softmax")Model: "sequential_3"
________________________________________________________________________________
Layer (type) Output Shape Param #
================================================================================
conv2d_13 (Conv2D) (None, 222, 222, 128) 3584
________________________________________________________________________________
leaky_re_lu_3 (LeakyReLU) (None, 222, 222, 128) 0
________________________________________________________________________________
max_pooling2d_10 (MaxPooling2D) (None, 111, 111, 128) 0
________________________________________________________________________________
conv2d_12 (Conv2D) (None, 109, 109, 128) 147584
________________________________________________________________________________
leaky_re_lu_2 (LeakyReLU) (None, 109, 109, 128) 0
________________________________________________________________________________
max_pooling2d_9 (MaxPooling2D) (None, 54, 54, 128) 0
________________________________________________________________________________
dropout_6 (Dropout) (None, 54, 54, 128) 0
________________________________________________________________________________
conv2d_11 (Conv2D) (None, 52, 52, 64) 73792
________________________________________________________________________________
leaky_re_lu_1 (LeakyReLU) (None, 52, 52, 64) 0
________________________________________________________________________________
max_pooling2d_8 (MaxPooling2D) (None, 26, 26, 64) 0
________________________________________________________________________________
dropout_5 (Dropout) (None, 26, 26, 64) 0
________________________________________________________________________________
conv2d_10 (Conv2D) (None, 24, 24, 32) 18464
________________________________________________________________________________
leaky_re_lu (LeakyReLU) (None, 24, 24, 32) 0
________________________________________________________________________________
max_pooling2d_7 (MaxPooling2D) (None, 12, 12, 32) 0
________________________________________________________________________________
flatten_3 (Flatten) (None, 4608) 0
________________________________________________________________________________
dropout_4 (Dropout) (None, 4608) 0
________________________________________________________________________________
dense_8 (Dense) (None, 512) 2359808
________________________________________________________________________________
activity_regularization (ActivityRe (None, 512) 0
________________________________________________________________________________
dense_7 (Dense) (None, 11) 5643
================================================================================
Total params: 2,608,875
Trainable params: 2,608,875
Non-trainable params: 0
________________________________________________________________________________
Ze względu na fakt, że pierwsza architektura, pomimo najprostrzej struktury, dawała relatywnie najlepsze wyniki, zdecydowaliśmy się do niej wrócić, jednak tym razem zasotowaliśmy modyfikacje w postaci regurlaryzacji oraz funkcji aktywacji, w postaci “leaky reLU”.
Podczas uczenia callbacki ustawione były na:
Zapisywanie modelu po każdej epoce;
Przerwanie procesu uczenia, jeżeli funkcja straty nie poprawi się na zbiorze walidacyjnym po 5 epokach;
Obniżenie learning rate, jeżeli funkcja straty nie poprawi się na zbiorze walidacyjnym po 3 epokach.
W porównaniu do wszystkich poprzednich struktur ta wypada najlepiej, zarówno na zbiorze uczącym (~67% celności) jak i walidacyjnym (~47% celności).
Niestety, pomimo lepszych wyników uczenia oraz obniżenia learning rate (widać że za pierwszym razem poprawił celność), model jest przeuczony.
Piąty projekt sieci
Pomimo faktu, że modele, które wykorzystywały wcześniej przetrenowaną sieć konwolucyjną ResNet50, okazały się być gorsze nawet od prostych struktur. Zdecydowaliśmy się użyć nowszej struktury DenseNet121, wykorzystującej bardziej zaawansowane połączenia resztowe.
Zdecydowaliśmy się na DenseNet121 z tego względu, że jest to najmniejsza struktura z architektur DenseNet, co jest ważne przy ograniczonych zasobach sprzętowych.
Tym razem uznaliśmy jednak, że abstrakcyjny charakter zadania wymaga przeszkolenia całej struktury na nowo, ponieważ wzorce wyuczone na zbiorze “Imagenet” mogą nie dawać zadowalających wyników.
conv_base <- application_densenet121(
weights = NULL,
include_top = TRUE,
classes = 11,
input_shape = c(224, 224, 3)
)
model <- conv_baseArchitektura ta okazała się być najlepsza ze wszystkich dotychczasowych, osiągając blisko 60% na zbiorze walidacyjnym.
Szósty projekt sieci
W tym podejściu postanowiliśmy zastosować predefiniowaną sieć NASNetMobile, ze względu na jej niewielki rozmiar oraz fakt, że jak na razie gotowe architektury, uczone od początku (losowo inicjalizowane wagi), dawały najlepsze wyniki.
conv_base <- application_nasnetmobile(
weights = NULL,
include_top = TRUE,
classes = 11,
input_shape = c(224, 224, 3)
)
model <- conv_baseWyniki okazały się być nieco gorsze od poprzedniej architektury oparej na DenseNet121, poniważ jest to około 55% celności na zbiorze walidacyjnym. Dodatkowo w tym przypadku efekt przeuczenia jest mniejszy niż przy poprzedniej architekturze, daje to więc potencjał do poprawy.
Klasyfikacja stylu obrazu
0 - Abstrakcjonizm ekspresyjny;
1 - Malowidło akcji;
2 - Kubizm anlityczny;
3 - Secesja;
4 - Barok;
5 - Malarstwo barwnych płaszczyzn;
6 - Realizm współczesny;
7 - Kubizm;
8 - Wczesny Renesans;
9 - Ekspresjonizm;
10 - Fowizm;
11 - Późny renesans;
12 - Impresjonizm;
13 - Manieryzm późnego renesansu;
14 - Minimalizm;
15 - Prymitywizm (Naïve art);
16 - Nowy realizm;
17 - Renesans północny;
18 - Puentylizm;
19 - Pop-art;
20 - Postimpresjonizm;
21 - Realizm;
22 - Rokoko;
23 - Romantyzm;
24 - Symbolizm;
25 - Kubizm syntetyczny;
26 - Ukiyo-e;
27 - Styl nieznany.
Pierwszy projekt sieci
Pierwszą architekturę sieci do rozpoznawania styli malarstwa postanowiliśmy oprzeć o wcześniej wyuczoną sieć ResNet50 z odmrożonymi dwoma blokami konwolucji.
W tym przypadku zdecydowaliśmy się na mniejszy blok gęsty względem architektury do rozpoznawania gatunków.
Kod
conv_base <- application_resnet50(
weights = "imagenet",
include_top = F,
input_shape = c(224,224,3)
)
model <- keras_model_sequential() %>%
conv_base %>%
layer_flatten() %>%
layer_dense(units = 256, activation = "relu") %>%
layer_dense(units = 27, activation = "softmax")Model: "sequential_4"
_____________________________________________________________________
Layer (type) Output Shape Param #
=====================================================================
resnet50 (Functional) (None, 7, 7, 2048) 23587712
_____________________________________________________________________
flatten_4 (Flatten) (None, 100352) 0
_____________________________________________________________________
dense_10 (Dense) (None, 256) 25690368
_____________________________________________________________________
dense_9 (Dense) (None, 27) 6939
=====================================================================
Total params: 49,285,019
Trainable params: 49,231,899
Non-trainable params: 53,120
_____________________________________________________________________
Podczas uczenia callbacki ustawione były na:
Zapisywanie modelu po każdej epoce;
Przerwanie procesu uczenia, jeżeli funkcja straty nie poprawi się na zbiorze walidacyjnym po 8 epokach;
Obniżenie learning rate, jeżeli funkcja straty nie poprawi się na zbiorze walidacyjnym po 4 epokach.
Niestety, proces uczenia został przerwany ze względu na limity platformy kaggle (kompilacja notatnika osiągnęła 12h), z tego względu dysponujemy jedynie logami dla rezultatów 27 epoki:
loss: 2.1323;
acc: 0.3101;
val_loss: 2.2895;
val_acc: 0.2795;
lr: 1.0000e-06.
Drugi projekt sieci
Jako następną architekturę sieci postanowliśmy skorzystać z używanej już wcześniej architektury, która została wykorzystana jako czwarta w zadniu klasyfikacji gatunków (Section 2.4), do czego skłoniły nas osiągane przez nią wyniki.
Kod
model <- keras_model_sequential() %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3),
input_shape = c(224, 224, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.2) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_dropout(rate = 0.3) %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3)) %>%
layer_activation_leaky_relu(alpha = 0.1) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dropout(rate = 0.5) %>%
layer_dense(units = 512, activation = "relu") %>%
layer_activity_regularization(l2 = 0.001) %>%
layer_dense(units = 27, activation = "softmax")Model: "sequential_5"
________________________________________________________________________________
Layer (type) Output Shape Param #
================================================================================
conv2d_17 (Conv2D) (None, 222, 222, 128) 3584
________________________________________________________________________________
leaky_re_lu_7 (LeakyReLU) (None, 222, 222, 128) 0
________________________________________________________________________________
max_pooling2d_14 (MaxPooling2D) (None, 111, 111, 128) 0
________________________________________________________________________________
conv2d_16 (Conv2D) (None, 109, 109, 128) 147584
________________________________________________________________________________
leaky_re_lu_6 (LeakyReLU) (None, 109, 109, 128) 0
________________________________________________________________________________
max_pooling2d_13 (MaxPooling2D) (None, 54, 54, 128) 0
________________________________________________________________________________
dropout_9 (Dropout) (None, 54, 54, 128) 0
________________________________________________________________________________
conv2d_15 (Conv2D) (None, 52, 52, 64) 73792
________________________________________________________________________________
leaky_re_lu_5 (LeakyReLU) (None, 52, 52, 64) 0
________________________________________________________________________________
max_pooling2d_12 (MaxPooling2D) (None, 26, 26, 64) 0
________________________________________________________________________________
dropout_8 (Dropout) (None, 26, 26, 64) 0
________________________________________________________________________________
conv2d_14 (Conv2D) (None, 24, 24, 32) 18464
________________________________________________________________________________
leaky_re_lu_4 (LeakyReLU) (None, 24, 24, 32) 0
________________________________________________________________________________
max_pooling2d_11 (MaxPooling2D) (None, 12, 12, 32) 0
________________________________________________________________________________
flatten_5 (Flatten) (None, 4608) 0
________________________________________________________________________________
dropout_7 (Dropout) (None, 4608) 0
________________________________________________________________________________
dense_12 (Dense) (None, 512) 2359808
________________________________________________________________________________
activity_regularization_1 (Activity (None, 512) 0
________________________________________________________________________________
dense_11 (Dense) (None, 27) 13851
================================================================================
Total params: 2,617,083
Trainable params: 2,617,083
Non-trainable params: 0
________________________________________________________________________________
Pomimo faktu, że i przy tej strukturze sieci następuje przeuczenie, osiąga ona taki sam wynik, na zbiorze uczącym po 3 epokach, co struktura oparta na ResNet50 osiągnęła po 27 epokach.
Trzeci projekt sieci
Wyniki uzyskane przy klasyfikacji gatunków, przez szkoloną od początku architekturę DenseNet121, skłoniły nas do użycia jej w zadaniu klasyfikacji stylów.
conv_base <- application_densenet121(
weights = NULL,
include_top = TRUE,
classes = 11,
input_shape = c(224, 224, 3)
)
model <- conv_baseDecyzja ta okazała się być trafiona, po raz pierwszy udało się osiągnąć celnośc powyżej 50% (~52%).
Ewaluacja modeli
Gatunki
Gatunki | ||||
|---|---|---|---|---|
model | loss | accuracy | top3 | top5 |
Arch1 | 1.535 | 0.456 | 0.783 | 0.913 |
Arch2 | 1.645 | 0.433 | 0.773 | 0.905 |
ResNet50 | 1.690 | 0.425 | 0.765 | 0.903 |
Arch3 | 1.595 | 0.483 | 0.772 | 0.907 |
DensNet121 | 1.240 | 0.566 | 0.792 | 0.917 |
NASNetMobile | 1.262 | 0.565 | 0.803 | 0.922 |
W przypadku modeli przeznaczonych do klasyfikacji gatunków malarstwa, najlepiej sprawdziły się architektury DenseNet121 i NASNetMobile trenowane od początku. Obie sieci osiągają bardzo zbliżone wyniki z niewielką przewagą na korzyść architektury DenseNet, ze względu na funkcję straty.
Najgorszą architekturą okzał się ResNet50, przetrenowany wcześniej na zbiorze “Imagenet”, z odmrożonymi dwoma blokami konwolucyjnymi. Przypuszczać można, że spowodowane jest to faktem, iż charakter zadania jest bardziej abstrakcyjny niż klasy zawarte w zbiorze uczącym tej architektury.
Warto zauważyć, że pierwsza architektura, będąca zarazem najprostrszą i ucząca się na niewielkim wycinku zbioru uczącego, osiągneła lepsze wyniki, niż struktury bardziej złożone.
Warto w tym przypadku nadmienićm że miara top 5 przy 11 kategoriach nie jest aż tak dobrym odzwierciedleniem jakości klasyfkiacji. Najważniejsze dalej będzie accuracy oraz top 3.
W przypadku miary top 3 dwa ostatnie modele osiągają zadowalające wyniki na poziomie ~80%
Style
Style | ||||
|---|---|---|---|---|
model | loss | accuracy | top3 | top5 |
ResNet50 | 2.295 | 0.275 | 0.770 | 0.892 |
Arch3 | 2.189 | 0.370 | 0.755 | 0.880 |
DensNet121 | 1.593 | 0.495 | 0.758 | 0.881 |
W przypadku klasyfikacji styli malarskich, wyniki są bardzo podobne do tych obserwowanych przy gatunkach. Najgorzej wypada wcześniej nauczona sieć ResNet50, osiągając bardzo niskie accuracy 27,5% i o dziwo najwyższe wyniki na miarach top 3 i top 5.
Ze względu na funkcję straty i accuracy, zdecydowanie najlepiej wypadła architektura DenseNet121 osiągając prawie 50% celności.
W tym przypadku metryka top 5 jest znacznie bardziej miarodajna, ze względu na fakt, że tym razem zadanie ma 27 kategorii.
Decydując się na model oparty na DenseNet121, jesteśmy w stanie osiągnać zadowaljący wynik 75% przy metryce top 3.
Predykcja
\[ \text{Gatunek: Pejzaż} \qquad \text{Styl: Realizm} \]
Gatunek | Prawdop. |
|---|---|
Martwa natura | 30.15 |
Malarstwo rodzajowe | 23.14 |
Szkic | 16.23 |
Pejzaż | 8.30 |
Ilustracja | 6.16 |
Styl | Prawdop. |
|---|---|
Minimalizm | 34.59 |
Nowy realizm | 34.34 |
Barok | 19.39 |
Realizm | 8.76 |
Kubizm | 2.55 |
\[ \text{Gatunek: Pejzaż miejski} \qquad \text{Styl: Realizm} \]
Gatunek | Prawdop. |
|---|---|
Malarstwo nagie | 51.29 |
Malarstwo rodzajowe | 27.10 |
Ilustracja | 8.45 |
Malarstwo abstrakcyjne | 7.64 |
Malarstwo religijne | 1.85 |
Styl | Prawdop. |
|---|---|
Minimalizm | 100 |
Barok | 0 |
Nowy realizm | 0 |
Wczesny Renesans | 0 |
Kubizm | 0 |
\[ \text{Gatunek: Gatunek nieznany} \qquad \text{Styl: Ukiyo-e} \]
Gatunek | Prawdop. |
|---|---|
Szkic | 57.66 |
Malarstwo rodzajowe | 19.14 |
Ilustracja | 18.38 |
Malarstwo religijne | 1.71 |
Pejzaż | 1.24 |
Styl | Prawdop. |
|---|---|
Minimalizm | 46.56 |
Nowy realizm | 19.95 |
Ekspresjonizm | 7.91 |
Ukiyo-e | 7.86 |
Kubizm | 5.61 |
\[ \text{Gatunek: Malarstwo rodzajowe} \qquad \text{Styl: Realizm} \]
Gatunek | Prawdop. |
|---|---|
Malarstwo nagie | 97.85 |
Pejzaż miejski | 1.75 |
Ilustracja | 0.28 |
Malarstwo rodzajowe | 0.09 |
Martwa natura | 0.03 |
Styl | Prawdop. |
|---|---|
Pop-art | 93.54 |
Późny renesans | 3.74 |
Ukiyo-e | 1.55 |
Abstrakcjonizm ekspresyjny | 0.52 |
Renesans północny | 0.28 |
\[ \text{Gatunek: Szkic} \qquad \text{Styl: Romantyzm} \]
Gatunek | Prawdop. |
|---|---|
Pejzaż miejski | 80.77 |
Malarstwo nagie | 18.26 |
Malarstwo rodzajowe | 0.76 |
Ilustracja | 0.19 |
Martwa natura | 0.01 |
Styl | Prawdop. |
|---|---|
Minimalizm | 93.66 |
Realizm | 3.02 |
Nowy realizm | 1.68 |
Prymitywizm (Naïve art) | 1.37 |
Renesans północny | 0.10 |
Linki do prac
Budowa modeli: https://www.kaggle.com/code/datachad/projekt-cv.
Ewaluacja modeli: https://www.kaggle.com/code/datachad/projekt-cv-eval.
Repozytorium: https://github.com/Chajf/Projekt_ComputerVision.